package utils

import (
	"errors"
	"math"
	"time"
)

const (
	// DateFormat 日期模板
	DateFormat = "2006-01-02"
	// TimeFormat 时间模板
	TimeFormat = "15:04:05"
)

var (
	ErrDateTimeCantParse = errors.New("当前时间字符串无法解析")
)

func GetCSTLocation() (*time.Location, error) {
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		return nil, err
	}

	return loc, nil
}

func ParseISOTime(dataTimeStr string) (time.Time, error) {
	layouts := []string{
		"2006-01-02 15:04:05-07:00",
		time.RFC3339,           // "2006-01-02T15:04:05Z07:00" 带时区的格式
		time.RFC3339Nano,       // "2006-01-02T15:04:05.999999999Z07:00" 带纳秒和时区的格式
		"2006-01-02T15:04:05Z", // "Z" 表示 UTC 时间
		"2006-01-02T15:04:05",  // 不带时区的格式
		"2006-01-02 15:04:05",  // 不带 T 和时区的格式
	}

	var (
		parseTime time.Time
		err       error
	)

	for _, layout := range layouts {
		parseTime, err = time.Parse(layout, dataTimeStr)
		if err == nil {
			return parseTime, nil
		}
	}

	return time.Time{}, ErrDateTimeCantParse
}

// ParseDateTime 年月日时分秒字符串转换成时间
func ParseDateTime(dateTimeStr string) (time.Time, error) {
	dateTimeLayout := DateFormat + " " + TimeFormat
	return time.Parse(dateTimeLayout, dateTimeStr)
}

func ParseCSTDateTime(dateTimeStr string) (*time.Time, error) {
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		return nil, err
	}
	dateTimeLayout := DateFormat + " " + TimeFormat
	t, err := time.ParseInLocation(dateTimeLayout, dateTimeStr, loc)
	return &t, err
}

// ParseDateTimeToCNShangHai 年月日时分秒字符串转换成时间
func ParseDateTimeToCNShangHai(dateTimeStr string) (time.Time, error) {
	dateTimeLayout := DateFormat + " " + TimeFormat
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		return time.Time{}, err
	}
	return time.ParseInLocation(dateTimeLayout, dateTimeStr, loc)
}

// FormatDate 转换时间为年月日字符串
func FormatDate(date time.Time) string {
	return date.Format(DateFormat)
}

// FormatTime 转换时间为时分秒字符串
func FormatTime(time time.Time) string {
	return time.Format(TimeFormat)
}

// FormatDateTime 将日期格式化成年月日时分秒字符串
func FormatDateTime(dateTime time.Time) string {
	return dateTime.Format(DateFormat + " " + TimeFormat)
}

// GetTimestamp 获取Unix时间戳
func GetTimestamp() int64 {
	return time.Now().Unix()
}

// ParseDate parses a string in the format "2006-01-02" and returns the corresponding time.Time value.
func ParseDate(dateStr string) (time.Time, error) {
	t, err := time.Parse("2006-01-02", dateStr)
	if err != nil {
		return time.Time{}, err
	}
	return t, nil
}

// CalculateDays calculates the number of days between two dates.
func CalculateDays(start, end time.Time) int {
	duration := end.Sub(start)
	return int(duration.Hours() / 24)
}

// CalculateWeeks calculates the number of weeks between two dates.
func CalculateWeeks(start, end time.Time) int {
	days := CalculateDays(start, end)
	return days / 7
}

// AddDays adds the specified number of days to the given date.
func AddDays(date time.Time, days int) time.Time {
	return date.AddDate(0, 0, days)
}

// IsWeekend checks if the given date falls on a weekend (Saturday or Sunday).
func IsWeekend(date time.Time) bool {
	weekday := date.Weekday()
	return weekday == time.Saturday || weekday == time.Sunday
}

// IsLeapYear checks if the given year is a leap year.
func IsLeapYear(year int) bool {
	if year%4 != 0 {
		return false
	}
	if year%100 == 0 && year%400 != 0 {
		return false
	}
	return true
}

// SubNatureDay 计算起始时间举例现在多少个自然日
func SubNatureDay(start time.Time) int {
	startZero := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, start.Location())
	return int(math.Floor(float64(time.Now().Sub(startZero).Hours()) / 24.0))
}
